package com.xunfang.portal.interceptor;

import com.xunfang.common.enumeration.impl.BusinessCode;
import com.xunfang.common.exception.Assert;
import com.xunfang.portal.config.UrlProperties;
import com.xunfang.portal.utils.JwtUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Objects;

/**
 * @author yellow Doctor
 * @date 2025-10-20
 * @desc https://blog.csdn.net/hekai7217
 *   01 拦截器的作用
 *       1、判断 token  +   拦截请求 做出判断  + ip(防止token劫持)
 *
 *   02 拦截器开发步骤 ?
 *       1、创建一个拦截器  JwtInterceptor 实现 HandlerInterceptor 接口
 *       2、重写 preHandle 的方法
 *       3、这个方法中进行token的校验
 *              拦截token、校验token
 *       4、把拦截器  JwtInterceptor 在 WebMvcConfigurer 中进行配置
 *       5、拦截中拦截所有的请求 需要校验token 但是、登录短信、swagger中有一些请求
 *            不需要token\需要配置白名单进行放行
 *           5.1  yml 中配置白名单
 *           5.2  通过 @ConfigurationProperties  读取白名单
 *           5.3  在   WebMvcConfigurer 中的  addInterceptors 方法中 添加白名单
 *
 *
 *   03 拦截器中的方法
 *        preHandle
 *           在请求controller 之前执行的方法
 *               这个方法的结果是boolean  如果是true 放行  false 拦截
 *
 */
@Component
//开启配置项自动读取填充到对象属性中，且填充后的对象自动加入IoC容器
@EnableConfigurationProperties(UrlProperties.class)
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtUtils jwtUtils;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("访问资源：{}", request.getRequestURI());
        //判断是否是options请求，如果是则直接放行
        if (request.getMethod().equalsIgnoreCase("OPTIONS")) {
            return true;
        }
        //获取请求头
        String token = request.getHeader("Authorization");

        //判断token是否存在
        Assert.error(Objects.isNull(token), BusinessCode.TOKEN_NOT_EXISTS);

        //验证token是否有效
        Assert.error(!jwtUtils.validateToken(token), BusinessCode.INVALID_TOKEN);

//        //判断IP地址是否相同
//        String ip = jwtUtils.getValue(token, "ip");
//        String remoteAddr = request.getRemoteAddr();
//        Assert.error(!ip.equals(remoteAddr), BusinessCode.INVALID_IP);

        //放行
        return true;
    }
}
